<?php

namespace App\Library\FeiShu;

use Illuminate\Support\Facades\Log;

class SendFs
{
    private $openUrl; // 机器人通知地址
    private $rootSecret; // 签名字符

    private string $title;
    private array  $fsContent   = [];
    private array  $messageBody = [];

    const ROBOT_WARNING                             = 1; // 报警
    const ROBOT_JOIN                                = 2; // 加盟名片新线索提醒
    const ROBOT_CHECK                               = 3; // 订单对账
    const ROBOT_INTERNAL                            = 4; // 内部推送
    const ROBOT_OPEN_SHOP                           = 5; // 开店业务推送
    const ROBOT_SITE_LOCATION                       = 6; // 选址开业
    const ROBOT_SHIJIA                              = 7; // 加盟名片时嘉新线索提醒
    const ROBOT_LANTU_CLUE                          = 8; // 蓝兔线索机器人
    const ROBOT_SABO                                = 9; // 萨博
    const ROBOT_KEBI                                = 10; // 克比
    const ROBOT_HUPO                                = 11; // 琥珀
    const ROBOT_NAZI                                = 12; // 纳兹
    const ROBOT_LIAO                                = 13; // 利奥
    const ROBOT_APPRAISE                            = 14; // 露西
    const ROBOT_SITE_LOCATION_NOT_CONFIRM           = 15; // 客户15天未落址
    const ROBOT_APPRAISE_TEST                       = 16; // 通知测试店铺机器人
    const ROBOT_AUDIT_LOG                           = 17; // 审计日志
    const ROBOT_DESIGN_NOTIFY                       = 18; // 设计通知
    const ROBOT_HIRE_NOTIFY                         = 19; // 招聘通知
    const ROBOT_WORK_ORDER_AUDIT_SUPPLIER           = 20; // 工单评价同步供应链机器人
    const ROBOT_DAILY_SYSTEM_MONITOR                = 21; // 日常系统监控
    const ROBOT_API_TIME                            = 22; // API-TIME
    const ROBOT_MY_BANK                             = 23; // 网商银行
    const ROBOT_APP_CRASH                           = 24; // APP-CRASH
    const ROBOT_OPEN_SHOP_PART_PAY                  = 27; // 开店业务部分支付
    const ROBOT_APPRAISE_FIVE_STAR                  = 25; // 5星评价单独群
    const ROBOT_WHO_BOT_AI_ERROR                    = 26; // 呼博特机器人异常推送
    const ROBOT_INVOICE                             = 28; // 订货发票相关推送通知消息
    const ROBOT_BUSINESS_INVOICE_ERROR              = 29; // 开票业务报错
    const ROBOT_WHO_BOT_AI_CALLING                  = 30; // AI呼叫机器人
    const ROBOT_FRIED_CHICKEN_LEG                   = 31; // 生炸鸡腿数据推送机器人
    const ROBOT_BUSINESS_CONTRACRT_TEMPLATE         = 32; // 加盟政策事件推送
    const ROBOT_BUSINESS_OPEN_SHOP_SIGN_ORDER_CLOSE = 33; // 加盟订单超时未支付作废通知
    const ROBOT_INTENDED_SITE_SELECTION_INSERT      = 34; // 新增意向选址推送机器人
    const ROBOT_AI_CHAT_DATA_STATISTICS             = 35; // AI客服数据统计机器人
    const ROBOT_INTENDED_SITE_SELECTION_CONFIRM_KF     = 36; // 确认选址推送机器人- 夸父选址
    const ROBOT_INTENDED_SITE_SELECTION_CONFIRM_DESIGN = 37; // 确认选址推送机器人 - 品牌设计
    const ROBOT_INTENDED_SITE_SELECTION_CONFIRM_ZF     = 38; // 确认选址推送机器人 - 浙江福建
    const ROBOT_CHECK_RECTIFY                          = 39; // 超期未整改飞书机器人
    const ROBOT_CHECK_RECTIFY_TWO                      = 40; // 超期未整改飞书机器人-2群
    const ROBOT_MERCHANT_PAY_SUCCESS                   = 41; // 美团点评商户通支付完成通知机器人
    const ROBOT_WX_APPLET_ARTICLE_READ_EVENT           = 42; // 微信加盟小程序文章阅读事件通知机器人
    const ROBOT_INTENDED_SITE_SELECTION_CONFIRM_DMG    = 43; // 确认选址推送机器人 - 开发群 development group
    const ROBOT_PREPARATION_PAY_SUCCESS                = 44; // 筹备支付成功群通知
    const ROBOT_NSQ_MONITOR                            = 45; // NSQ监控
    const ROBOT_ADD_WORK_ORDER_PK_1                    = 46; // 新增品质工单飞书群通知-供应商品控群
    const ROBOT_ADD_WORK_ORDER_PK_2                    = 47; // 新增品质工单飞书群通知-PDCA 品控群
    const ROBOT_TANG_XIAO                              = 48; // 外卖组机器人
    const ROBOT_ADD_WORK_ORDER_CP_1                    = 49; // 新增仓储配送问题飞书群通知

    private function __construct(int $robot)
    {
        switch ($robot) {
            case self::ROBOT_WARNING:
                $this->openUrl    = config('feishu.robots.warning.url');
                $this->rootSecret = config('feishu.robots.warning.token');
                break;
            case self::ROBOT_JOIN:
                $this->openUrl    = config('feishu.robots.join.url');
                $this->rootSecret = config('feishu.robots.join.token');
                break;
            case self::ROBOT_CHECK:
                $this->openUrl    = config('feishu.robots.check.url');
                $this->rootSecret = config('feishu.robots.check.token');
                break;
            case self::ROBOT_INTERNAL:
                $this->openUrl    = config('feishu.robots.internal.url');
                $this->rootSecret = config('feishu.robots.internal.token');
                break;
            case self::ROBOT_OPEN_SHOP:
                $this->openUrl    = config('feishu.robots.open_shop.url');
                $this->rootSecret = config('feishu.robots.open_shop.token');
                break;
            case self::ROBOT_SITE_LOCATION:
                $this->openUrl    = config('feishu.robots.site_location.url');
                $this->rootSecret = config('feishu.robots.site_location.token');
                break;
            case self::ROBOT_SHIJIA:
                $this->openUrl    = config('feishu.robots.shijia.url');
                $this->rootSecret = config('feishu.robots.shijia.token');
                break;
            case self::ROBOT_LANTU_CLUE:
                $this->openUrl    = config('feishu.robots.lantu-clue.url');
                $this->rootSecret = config('feishu.robots.lantu-clue.token');
                break;
            case self::ROBOT_SABO:
                $this->openUrl    = config('feishu.robots.sabo.url');
                $this->rootSecret = config('feishu.robots.sabo.token');
                break;
            case self::ROBOT_KEBI:
                $this->openUrl    = config('feishu.robots.kebi.url');
                $this->rootSecret = config('feishu.robots.kebi.token');
                break;
            case self::ROBOT_HUPO:
                $this->openUrl    = config('feishu.robots.hupo.url');
                $this->rootSecret = config('feishu.robots.hupo.token');
                break;
            case self::ROBOT_NAZI:
                $this->openUrl    = config('feishu.robots.nazi.url');
                $this->rootSecret = config('feishu.robots.nazi.token');
                break;
            case self::ROBOT_LIAO:
                $this->openUrl    = config('feishu.robots.liao.url');
                $this->rootSecret = config('feishu.robots.liao.token');
                break;
            case self::ROBOT_APPRAISE:
                $this->openUrl    = config('feishu.robots.appraise.url');
                $this->rootSecret = config('feishu.robots.appraise.token');
                break;
            case self::ROBOT_SITE_LOCATION_NOT_CONFIRM:
                $this->openUrl    = config('feishu.robots.site_location_not_confirm.url');
                $this->rootSecret = config('feishu.robots.site_location_not_confirm.token');
                break;
            case self::ROBOT_APPRAISE_TEST:
                $this->openUrl    = config('feishu.robots.appraiseTest.url');
                $this->rootSecret = config('feishu.robots.appraiseTest.token');
                break;
            case self::ROBOT_AUDIT_LOG:
                $this->openUrl    = config('feishu.robots.auditLog.url');
                $this->rootSecret = config('feishu.robots.auditLog.token');
                break;
            case self::ROBOT_DESIGN_NOTIFY:
                $this->openUrl    = config('feishu.robots.designNotify.url');
                $this->rootSecret = config('feishu.robots.designNotify.token');
                break;
            case self::ROBOT_HIRE_NOTIFY:
                $this->openUrl    = config('feishu.robots.hire.url');
                $this->rootSecret = config('feishu.robots.hire.token');
                break;
            default:
                throw new \Exception('不存在的飞书机器人');
        }
    }

    public static function newRobot(int $robot = self::ROBOT_WARNING)
    {
        return new static($robot);
    }

    public function coverConfig(string $openUrl, string $secret): SendFs
    {
        $this->openUrl    = $openUrl;
        $this->rootSecret = $secret;
        return $this;
    }

    public function getOpenUrl()
    {
        return $this->openUrl;
    }

    public function getRootSecret()
    {
        return $this->rootSecret;
    }

    /**
     * 设置标题内容
     * @param string $title
     * @param string $content
     * @return $this
     */
    public function setTitleContent(string $title, string $content, string $atUid = '', bool $withPrefix = true): self
    {
        $this->title = ($withPrefix ? "通知-" . config('app.env') . "：{$title}" : $title);

        if ($content) {
            $this->fsContent[] = ['tag' => 'text', 'text' => $content];
        }

        if ($atUid) {
            $this->fsContent[] = ['tag' => 'at', 'user_id' => $atUid];
        }

        return $this;
    }

    public function setAtUid(string $atUid): self
    {
        $this->fsContent[] = ['tag' => 'at', 'user_id' => $atUid];

        return $this;
    }

    public function setUrl(string $text, string $url)
    {
        $this->fsContent[] = [
            'tag'  => 'a',
            'text' => $text,
            'href' => $url,
        ];
        return $this;
    }

    /**
     * HmacSHA256 算法计算签名
     * @param $time
     * @return string
     */
    private function makeSign($time)
    {
        $string = "{$time}\n{$this->rootSecret}";
        return base64_encode(hash_hmac('sha256', "", $string, true));
    }

    public function setContentMessageBody()
    {
        $this->messageBody = [
            'msg_type' => 'post',
            'content'  => [
                'post' => [
                    'zh_cn' => [
                        'title'   => $this->title,
                        'content' => [
                            $this->fsContent,
                        ]
                    ]
                ]
            ],
        ];
    }

    public function setCardMessageBody(array $messageData = [])
    {
        $this->messageBody = [
            'msg_type' => 'interactive',
            'card'     => $messageData
        ];
        return $this;
    }

    public function setMessageBody(array $messageBody): self
    {
        $this->messageBody = $messageBody;
        return $this;
    }

    /**
     * 发送请求
     * @return mixed
     */
    public function send()
    {
        $timestamp = time();

        $baseData = [
            'timestamp' => $timestamp,
            'sign'      => $this->makeSign($timestamp)
        ];

        if (!empty($this->fsContent)) {
            $this->setContentMessageBody();
        }

        $data = json_encode(array_merge($baseData, $this->messageBody), JSON_UNESCAPED_UNICODE);

        $curlObj = curl_init();
        $ssl     = stripos($this->openUrl, 'https://') === 0 ? true : false;
        $options = [
            CURLOPT_URL            => $this->openUrl,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_POST           => 1,
            CURLOPT_POSTFIELDS     => $data,
            CURLOPT_FOLLOWLOCATION => 1,
            CURLOPT_AUTOREFERER    => 1,
            CURLOPT_USERAGENT      => 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)',
            CURLOPT_TIMEOUT        => 1, // 1秒超时
            CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_0,
            CURLOPT_HTTPHEADER     => ['Expect:'],
            CURLOPT_IPRESOLVE      => CURL_IPRESOLVE_V4,
            CURLOPT_HTTPHEADER     => ['Content-Type: application/json; charset=utf-8'],
        ];

        if ($ssl) {
            //support https
            $options[CURLOPT_SSL_VERIFYHOST] = false;
            $options[CURLOPT_SSL_VERIFYPEER] = false;
        }
        curl_setopt_array($curlObj, $options);
        $returnData = curl_exec($curlObj);
        if (curl_errno($curlObj)) {
            //error message
            $returnData = curl_error($curlObj);
        }
        curl_close($curlObj);
        return $returnData;
    }
}
